Plot result
source("script/04A-self_assembly-02-read_community_data.R")
if(write_all_csv) {
fwrite(df_self_assembly, root$find_file("output/report/data/temp/df_self_assembly.txt"))
fwrite(df_mono, root$find_file("output/report/data/temp/df_mono.txt"))
fwrite(df_grower, root$find_file("output/report/data/temp/df_grower.txt"))
}
Richness

Relative abundances, 4 self-assembled communities for example

Relative abundances of 96 self-assembled communities at 10th transfer
p_self_assembly[[4]]

pdf(root$find_file("output/report/figure/04A-self_assembly-self_assembled_communities.pdf")); p_self_assembly[[4]]; invisible(dev.off())
Monoculture growth
p_mono[[2]]

pdf(root$find_file("output/report/figure/04A-self_assembly-monoculture_growth.pdf")); p_mono[[2]]; invisible(dev.off())
List of grower identified by monoculture
df_mono %>%
filter(Type == "consumer", Transfer == 10) %>%
pull(ID) %>% as.character() %>% paste0(collapse = ", ")
[1] "13, 16, 17, 18, 21, 33, 38, 49, 51, 66, 68, 74, 83, 85, 94, 110, 115, 118, 142, 152, 155, 158, 171, 177, 183, 188, 191"
Pairwise competition
Species list from equilibrial community W0
df_self_assembly %>%
filter(Type == "consumer", Transfer == 10) %>%
filter(Community == "W14") %>%
pull(ID) %>%
paste0(collapse = ", ")
Essential functions for community self-assembly
source_python("script/04A-self_assembly-01-experiment_functions.py")
Pairwise competition in self-assembled community W0
# Assumptions
assumptions = a_default.copy() # Start with default parameters
assumptions.update({'n_wells':96, 'c1' :0.01, 'muc':0.1, 'm':0}) # Switch off mortality
# Prepare experiment
params, species_pool = prepare_experiment(assumptions)
## Simulation parameters
params_simulation = {
"n_propagation": 12, # Length of propagation, or hours within a growth cycle
"n_transfer": 10, # Number of transfer, or number of passage
"dilution": 1/1000, # Dilution factor for transfer
}
# Make initial state
N0 = make_synthetic_community(species_list = [13, 16, 17, 33, 49, 51, 68, 74, 85, 94, 152, 155, 171, 188, 191], assumptions = assumptions, number_species = 2, initial_frequency = [[0.5, 0.5], [0.95, 0.05], [0.05, 0.95]])
init_state = make_initial_state(assumptions, N0)
# Make plate
plate = Community(init_state, dynamics, params, scale = 10**6, parallel = True)
# Simulation
simulate_community(plate, assumptions, params_simulation, file_name = "data/self_assembly-pair-W0", write_composition = True)
Pairwise competition in self-assembled community W1
# Assumptions
assumptions = a_default.copy() # Start with default parameters
assumptions.update({'n_wells':96, 'c1' :0.01, 'muc':0.1, 'm':0}) # Switch off mortality
# Prepare experiment
params, species_pool = prepare_experiment(assumptions)
## Simulation parameters
params_simulation = {
"n_propagation": 12, # Length of propagation, or hours within a growth cycle
"n_transfer": 10, # Number of transfer, or number of passage
"dilution": 1/1000, # Dilution factor for transfer
}
# Make initial state
N0 = make_synthetic_community(species_list = [18, 21, 38, 51, 94, 142, 152, 155, 158, 171, 183, 188], assumptions = assumptions, number_species = 2, initial_frequency = [[0.5, 0.5], [0.95, 0.05], [0.05, 0.95]])
init_state = make_initial_state(assumptions, N0)
# Make plate
plate = Community(init_state, dynamics, params, scale = 10**6, parallel = True)
# Simulation
simulate_community(plate, assumptions, params_simulation, file_name = "data/self_assembly-pair-W1", write_composition = True)
Pairwise competition in self-assembled community W2
# Assumptions
assumptions = a_default.copy() # Start with default parameters
assumptions.update({'n_wells':96, 'c1' :0.01, 'muc':0.1, 'm':0}) # Switch off mortality
# Prepare experiment
params, species_pool = prepare_experiment(assumptions)
## Simulation parameters
params_simulation = {
"n_propagation": 12, # Length of propagation, or hours within a growth cycle
"n_transfer": 10, # Number of transfer, or number of passage
"dilution": 1/1000, # Dilution factor for transfer
}
# Make initial state
N0 = make_synthetic_community(species_list = [13, 16, 18, 21, 33, 66, 85, 110, 115, 118, 155, 171, 177, 191], assumptions = assumptions, number_species = 2, initial_frequency = [[0.5, 0.5], [0.95, 0.05], [0.05, 0.95]])
init_state = make_initial_state(assumptions, N0)
# Make plate
plate = Community(init_state, dynamics, params, scale = 10**6, parallel = True)
# Simulation
simulate_community(plate, assumptions, params_simulation, file_name = "data/self_assembly-pair-W2", write_composition = True)
Pairwise competition in self-assembled community W14
# Assumptions
assumptions = a_default.copy() # Start with default parameters
assumptions.update({'n_wells':96, 'c1' :0.01, 'muc':0.1, 'm':0}) # Switch off mortality
# Prepare experiment
params, species_pool = prepare_experiment(assumptions)
## Simulation parameters
params_simulation = {
"n_propagation": 12, # Length of propagation, or hours within a growth cycle
"n_transfer": 10, # Number of transfer, or number of passage
"dilution": 1/1000, # Dilution factor for transfer
}
# Make initial state
N0 = make_synthetic_community(species_list = [13, 16, 18, 21, 51, 52, 74, 94, 115, 138, 142, 152, 155, 158, 171, 177, 180, 183, 200], assumptions = assumptions, number_species = 2, initial_frequency = [[0.5, 0.5], [0.95, 0.05], [0.05, 0.95]])
init_state = make_initial_state(assumptions, N0)
# Make plate
plate = Community(init_state, dynamics, params, scale = 10**6, parallel = True)
# Simulation
simulate_community(plate, assumptions, params_simulation, file_name = "data/self_assembly-pair-W14", write_composition = True)
Run W14 for longer
# Assumptions
assumptions = a_default.copy() # Start with default parameters
assumptions.update({'n_wells':96, 'c1' :0.01, 'muc':0.1, 'm':0}) # Switch off mortality
# Prepare experiment
params, species_pool = prepare_experiment(assumptions)
## Simulation parameters
params_simulation = {
"n_propagation": 12, # Length of propagation, or hours within a growth cycle
"n_transfer": 30, # Number of transfer, or number of passage
"dilution": 1/1000, # Dilution factor for transfer
}
# Make initial state
N0 = make_synthetic_community(species_list = [13, 16, 18, 21, 51, 52, 74, 94, 115, 138, 142, 152, 155, 158, 171, 177, 180, 183, 200], assumptions = assumptions, number_species = 2, initial_frequency = [[0.5, 0.5], [0.95, 0.05], [0.05, 0.95]])
init_state = make_initial_state(assumptions, N0)
# Make plate
plate = Community(init_state, dynamics, params, scale = 10**6, parallel = True)
# Simulation
simulate_community(plate, assumptions, params_simulation, file_name = "data/self_assembly-pair-W14a", write_composition = True)
Plot result
if(write_all_csv) fwrite(df_pair_interaction, root$find_file("output/report/data/temp/df_pair_interaction.txt"))
List of grower identified by monoculture
df_mono %>%
filter(Type == "consumer", Transfer == 10) %>%
pull(ID) %>% as.character() %>% paste0(collapse = ", ")
[1] "13, 16, 17, 18, 21, 33, 38, 49, 51, 66, 68, 74, 83, 85, 94, 110, 115, 118, 142, 152, 155, 158, 171, 177, 183, 188, 191"
Pairwise competition in self-assembled communities
p_pair
[[1]]
[[2]]
[[3]]
[[4]]
[[5]]





pdf(root$find_file("output/report/figure/04A-self_assembly-W14_pairwise_competition.pdf")); p_pair[[3]]; invisible(dev.off())
pdf(root$find_file("output/report/figure/04A-self_assembly-W14a_pairwise_competition.pdf")); p_pair[[4]]; invisible(dev.off())
Number of interaction types
p_interaction_frequency

pdf(root$find_file("output/report/figure/04A-self_assembly-pairwise_interactions.pdf"), width = 8, height = 5); p_interaction_frequency; invisible(dev.off())
LS0tCnRpdGxlOiAiU2VsZi1hc3NlbWJseSB1c2luZyBtZWNoYW5pc3RpYyBjb25zdW1lci1yZXNvdXJjZSBtb2RlbHMiCmF1dGhvcjogIkNoYW5nLVl1IENoYW5nIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdG9jOiB5ZXMKbGlua2NvbG9yOiByZWQKZm9udHNpemU6IDEycHQKdXJsY29sb3I6IGJsdWUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZSA9IEZBTFNFfQojIEtuaXRyIG9wdGlvbnMKa25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGNhY2hlID0gRkFMU0UsIAogIGVjaG8gPSBUUlVFLAoJZmlnLmFsaWduID0gImNlbnRlciIsCglmaWcuaGVpZ2h0ID0gMywKCWZpZy53aWR0aCA9IDMpCgojIFBhY2thZ2VzCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoaW52bmV0KQpsaWJyYXJ5KHJldGljdWxhdGUpICMgUHl0aG9uIGludGVyZmFjZQpyZXRpY3VsYXRlOjp1c2VfcHl0aG9uKCd+L2FuYWNvbmRhMy9iaW4vcHl0aG9uMy43bScpICMgVXNlIHRoaXMgcHl0aG9uIHZlcnNpb24KCiMgTG9jYWwgZGlyZWN0b3J5IGFuZCBmdW5jdGlvbnMKcm9vdCA8LSBycHJvanJvb3Q6OmlzX3JfcGFja2FnZSAjIFBhY2thZ2Ugcm9vdApzb3VyY2Uocm9vdCRmaW5kX2ZpbGUoIm1pc2MvdXRpbHMuUiIpKQpzb3VyY2Uocm9vdCRmaW5kX2ZpbGUoIm1pc2MvbmV0d29ya19mdW5jdGlvbnMuUiIpKQp3cml0ZV9hbGxfY3N2IDwtIFRSVUUKd3JpdGVfYWxsX3BkZiA8LSBUUlVFCmBgYAoKUHl0aG9uIHZlcnNpb24KCmBgYHtweXRob259CmltcG9ydCBzeXMKcHJpbnQoc3lzLnZlcnNpb24pCmBgYAoKIyBTZXR0aW5ncwoKIyMgSW1wb3J0IHBhY2thZ2VzCgpgYGB7cHl0aG9uIGVjaG8gPSBUfQpmcm9tIElQeXRob24uZGlzcGxheSBpbXBvcnQgSW1hZ2UKZnJvbSBjb21tdW5pdHlfc2ltdWxhdG9yIGltcG9ydCAqCmZyb20gY29tbXVuaXR5X3NpbXVsYXRvci51c2VydG9vbHMgaW1wb3J0ICoKZnJvbSBjb21tdW5pdHlfc2ltdWxhdG9yLnZpc3VhbGl6YXRpb24gaW1wb3J0ICoKaW1wb3J0IHNlYWJvcm4gYXMgc25zCmltcG9ydCBtYXRwbG90bGliLnB5cGxvdCBhcyBwbHQKZnJvbSBtYXRwbG90bGliLmJhY2tlbmRzIGltcG9ydCBiYWNrZW5kX3BkZiBhcyBicGRmCiNjb2xvcnMgPSBzbnMuY29sb3JfcGFsZXR0ZSgpCiMlbWF0cGxvdGxpYiBpbmxpbmUKYGBgCgoKIyBGdW5jdGlvbnMgZm9yIHNpbXVsYXRpb24KCjEuIGBwcmVwYXJlX2V4cGVyaW1lbnQoYXNzdW1wdGlvbilgCiAgICAtIE1ha2UgYHBhcmFtc2AgYW5kIGBzcGVjaWVzX3Bvb2xgIAoKMi4gYG1ha2Vfc3ludGhldGljXyooKWAKICAgIC0gYG1ha2Vfc3ludGhldGljX21vbm8oYXNzdW1wdGlvbnMpYCAKICAgIC0gYG1ha2Vfc3ludGhldGljX2NvbW11bml0eSgpYAogICAgLSBgbWFrZV9pbml0aWFsX3N0YXRlKGFzc211cHRpb25zLCBOMClgIAoKMy4gYHNpbWx1YXRlX2NvbW11bml0eShwbGF0ZSwgYXNzdW1wdGlvbnMsIHBhcmFtc19zaW11bGF0aW9uLCBmaWxlX25hbWUpYAoKYGBge3J9Ck4wID0gbWFrZV9zeW50aGV0aWNfY29tbXVuaXR5KHNwZWNpZXNfbGlzdCA9IFsxMywgMTYsIDE3LCAzMywgNDksIDUxLCA2OCwgNzQsIDg1LCA5NCwgMTUyLCAxNTUsIDE3MSwgMTg4LCAxOTFdLCBhc3N1bXB0aW9ucyA9IGFzc3VtcHRpb25zLCBudW1iZXJfc3BlY2llcyA9IDIsIGluaXRpYWxfZnJlcXVlbmN5ID0gW1swLjUsIDAuNV0sIFswLjk1LCAwLjA1XSwgWzAuMDUsIDAuOTVdXSkKaW5pdF9zdGF0ZSA9IG1ha2VfaW5pdGlhbF9zdGF0ZShhc3N1bXB0aW9ucywgTjApCgojIE1ha2UgcGxhdGUKcGxhdGUgPSBDb21tdW5pdHkoaW5pdF9zdGF0ZSwgZHluYW1pY3MsIHBhcmFtcywgc2NhbGUgPSAxMCoqNiwgcGFyYWxsZWwgPSBUcnVlKQoKIyBTaW11bGF0aW9uCnNpbXVsYXRlX2NvbW11bml0eShwbGF0ZSwgYXNzdW1wdGlvbnMsIHBhcmFtc19zaW11bGF0aW9uLCBmaWxlX25hbWUgPSAiZGF0YS9zZWxmX2Fzc2VtYmx5LXBhaXItVzAiLCB3cml0ZV9jb21wb3NpdGlvbiA9IFRydWUpCmBgYAoKCmBgYHtyfQpzb3VyY2VfcHl0aG9uKCJzY3JpcHQvMDRBLXNlbGZfYXNzZW1ibHktMDEtZXhwZXJpbWVudF9mdW5jdGlvbnMucHkiKQpgYGAKCiMgU2ltdWxhdGlvbgoKUGFyYW1ldGVycwoKYGBge3B5dGhvbn0KIyBBc3N1bXB0aW9ucwphc3N1bXB0aW9ucyA9IGFfZGVmYXVsdC5jb3B5KCkgIyBTdGFydCB3aXRoIGRlZmF1bHQgcGFyYW1ldGVycwphc3N1bXB0aW9ucy51cGRhdGUoeyduX3dlbGxzJzo5NiwgJ2MxJyA6MC4wMSwgJ211Yyc6MC4xLCAnbSc6MH0pICMgU3dpdGNoIG9mZiBtb3J0YWxpdHkKCiMgUHJlcGFyZSBleHBlcmltZW50CnBhcmFtcywgc3BlY2llc19wb29sID0gcHJlcGFyZV9leHBlcmltZW50KGFzc3VtcHRpb25zKQoKIyMgU2ltdWxhdGlvbiBwYXJhbWV0ZXJzCnBhcmFtc19zaW11bGF0aW9uID0gewogICAgIm5fcHJvcGFnYXRpb24iOiAxMiwgIyBMZW5ndGggb2YgcHJvcGFnYXRpb24sIG9yIGhvdXJzIHdpdGhpbiBhIGdyb3d0aCBjeWNsZQogICAgIm5fdHJhbnNmZXIiOiAxMCwgIyBOdW1iZXIgb2YgdHJhbnNmZXIsIG9yIG51bWJlciBvZiBwYXNzYWdlCiAgICAiZGlsdXRpb24iOiAxLzEwMDAsICMgRGlsdXRpb24gZmFjdG9yIGZvciB0cmFuc2Zlcgp9CmBgYAoKCjk2IHNlbGYtYXNzZW1ibGVkIGNvbW11bml0aWVzIAoKYGBge3B5dGhvbn0KIyBNYWtlIGluaXRpYWwgc3RhdGUKaW5pdF9zdGF0ZSA9IE1ha2VJbml0aWFsU3RhdGUoYXNzdW1wdGlvbnMpCgojIE1ha2UgcGxhdGUKcGxhdGUgPSBDb21tdW5pdHkoaW5pdF9zdGF0ZSwgZHluYW1pY3MsIHBhcmFtcywgc2NhbGUgPSAxMCoqNiwgcGFyYWxsZWwgPSBUcnVlKSAKCiMgU2ltdWxhdGlvbgpzaW11bGF0ZV9jb21tdW5pdHkocGxhdGUsIGFzc3VtcHRpb25zLCBwYXJhbXNfc2ltdWxhdGlvbiwgZmlsZV9uYW1lID0gImRhdGEvc2VsZl9hc3NlbWJseS1jb21tdW5pdHkiLCB3cml0ZV9jb21wb3NpdGlvbiA9IFRydWUpCmBgYAoKTW9ub2N1bHR1cmVzCgpgYGB7cHl0aG9ufQojIE1ha2UgaW5pdGlhbCBzdGF0ZQpOMCA9IG1ha2Vfc3ludGhldGljX21vbm8oYXNzdW1wdGlvbnMpCmluaXRfc3RhdGUgPSBtYWtlX2luaXRpYWxfc3RhdGUoYXNzdW1wdGlvbnMsIE4wKQoKIyBNYWtlIHBsYXRlCnBsYXRlID0gQ29tbXVuaXR5KGluaXRfc3RhdGUsIGR5bmFtaWNzLCBwYXJhbXMsIHNjYWxlID0gMTAqKjYsIHBhcmFsbGVsID0gVHJ1ZSkgCgojIFNpbXVsYXRpb24Kc2ltdWxhdGVfY29tbXVuaXR5KHBsYXRlLCBhc3N1bXB0aW9ucywgcGFyYW1zX3NpbXVsYXRpb24sIGZpbGVfbmFtZSA9ICJkYXRhL3NlbGZfYXNzZW1ibHktbW9ubyIsIHdyaXRlX2NvbXBvc2l0aW9uID0gVHJ1ZSkKYGBgCgojIFBsb3QgcmVzdWx0CgpgYGB7cn0Kc291cmNlKCJzY3JpcHQvMDRBLXNlbGZfYXNzZW1ibHktMDItcmVhZF9jb21tdW5pdHlfZGF0YS5SIikKYGBgCgpgYGB7cn0KaWYod3JpdGVfYWxsX2NzdikgewogIGZ3cml0ZShkZl9zZWxmX2Fzc2VtYmx5LCByb290JGZpbmRfZmlsZSgib3V0cHV0L3JlcG9ydC9kYXRhL3RlbXAvZGZfc2VsZl9hc3NlbWJseS50eHQiKSkKICBmd3JpdGUoZGZfbW9ubywgcm9vdCRmaW5kX2ZpbGUoIm91dHB1dC9yZXBvcnQvZGF0YS90ZW1wL2RmX21vbm8udHh0IikpCiAgZndyaXRlKGRmX2dyb3dlciwgcm9vdCRmaW5kX2ZpbGUoIm91dHB1dC9yZXBvcnQvZGF0YS90ZW1wL2RmX2dyb3dlci50eHQiKSkKfQpgYGAKCgpSaWNobmVzcwoKYGBge3J9CnBfc2VsZl9hc3NlbWJseVtbMV1dCmBgYAoKUmVsYXRpdmUgYWJ1bmRhbmNlcywgNCBzZWxmLWFzc2VtYmxlZCBjb21tdW5pdGllcyBmb3IgZXhhbXBsZQoKYGBge3J9CnBfc2VsZl9hc3NlbWJseVtbM11dCmBgYAoKUmVsYXRpdmUgYWJ1bmRhbmNlcyBvZiA5NiBzZWxmLWFzc2VtYmxlZCBjb21tdW5pdGllcyBhdCAxMHRoIHRyYW5zZmVyCgpgYGB7cn0KcF9zZWxmX2Fzc2VtYmx5W1s0XV0KcGRmKHJvb3QkZmluZF9maWxlKCJvdXRwdXQvcmVwb3J0L2ZpZ3VyZS8wNEEtc2VsZl9hc3NlbWJseS1zZWxmX2Fzc2VtYmxlZF9jb21tdW5pdGllcy5wZGYiKSk7IHBfc2VsZl9hc3NlbWJseVtbNF1dOyBpbnZpc2libGUoZGV2Lm9mZigpKQpgYGAKCk1vbm9jdWx0dXJlIGdyb3d0aAoKYGBge3J9CnBfbW9ub1tbMl1dCnBkZihyb290JGZpbmRfZmlsZSgib3V0cHV0L3JlcG9ydC9maWd1cmUvMDRBLXNlbGZfYXNzZW1ibHktbW9ub2N1bHR1cmVfZ3Jvd3RoLnBkZiIpKTsgcF9tb25vW1syXV07IGludmlzaWJsZShkZXYub2ZmKCkpCmBgYAoKTGlzdCBvZiBncm93ZXIgaWRlbnRpZmllZCBieSBtb25vY3VsdHVyZQoKYGBge3J9CmRmX21vbm8gJT4lCiAgZmlsdGVyKFR5cGUgPT0gImNvbnN1bWVyIiwgVHJhbnNmZXIgPT0gMTApICU+JQogIHB1bGwoSUQpICU+JSBhcy5jaGFyYWN0ZXIoKSAlPiUgcGFzdGUwKGNvbGxhcHNlID0gIiwgIikKYGBgCgoKIyBQYWlyd2lzZSBjb21wZXRpdGlvbgoKU3BlY2llcyBsaXN0IGZyb20gZXF1aWxpYnJpYWwgY29tbXVuaXR5IFcwCgpgYGB7cn0KZGZfc2VsZl9hc3NlbWJseSAlPiUKICBmaWx0ZXIoVHlwZSA9PSAiY29uc3VtZXIiLCBUcmFuc2ZlciA9PSAxMCkgJT4lCiAgZmlsdGVyKENvbW11bml0eSA9PSAiVzE0IikgJT4lIAogIHB1bGwoSUQpICU+JQogIHBhc3RlMChjb2xsYXBzZSA9ICIsICIpCmBgYAoKRXNzZW50aWFsIGZ1bmN0aW9ucyBmb3IgY29tbXVuaXR5IHNlbGYtYXNzZW1ibHkKCmBgYHtyfQpzb3VyY2VfcHl0aG9uKCJzY3JpcHQvMDRBLXNlbGZfYXNzZW1ibHktMDEtZXhwZXJpbWVudF9mdW5jdGlvbnMucHkiKQpgYGAKClBhaXJ3aXNlIGNvbXBldGl0aW9uIGluIHNlbGYtYXNzZW1ibGVkIGNvbW11bml0eSBXMAoKYGBge3B5dGhvbn0KIyBBc3N1bXB0aW9ucwphc3N1bXB0aW9ucyA9IGFfZGVmYXVsdC5jb3B5KCkgIyBTdGFydCB3aXRoIGRlZmF1bHQgcGFyYW1ldGVycwphc3N1bXB0aW9ucy51cGRhdGUoeyduX3dlbGxzJzo5NiwgJ2MxJyA6MC4wMSwgJ211Yyc6MC4xLCAnbSc6MH0pICMgU3dpdGNoIG9mZiBtb3J0YWxpdHkKCiMgUHJlcGFyZSBleHBlcmltZW50CnBhcmFtcywgc3BlY2llc19wb29sID0gcHJlcGFyZV9leHBlcmltZW50KGFzc3VtcHRpb25zKQoKIyMgU2ltdWxhdGlvbiBwYXJhbWV0ZXJzCnBhcmFtc19zaW11bGF0aW9uID0gewogICAgIm5fcHJvcGFnYXRpb24iOiAxMiwgIyBMZW5ndGggb2YgcHJvcGFnYXRpb24sIG9yIGhvdXJzIHdpdGhpbiBhIGdyb3d0aCBjeWNsZQogICAgIm5fdHJhbnNmZXIiOiAxMCwgIyBOdW1iZXIgb2YgdHJhbnNmZXIsIG9yIG51bWJlciBvZiBwYXNzYWdlCiAgICAiZGlsdXRpb24iOiAxLzEwMDAsICMgRGlsdXRpb24gZmFjdG9yIGZvciB0cmFuc2Zlcgp9CgojIE1ha2UgaW5pdGlhbCBzdGF0ZQpOMCA9IG1ha2Vfc3ludGhldGljX2NvbW11bml0eShzcGVjaWVzX2xpc3QgPSBbMTMsIDE2LCAxNywgMzMsIDQ5LCA1MSwgNjgsIDc0LCA4NSwgOTQsIDE1MiwgMTU1LCAxNzEsIDE4OCwgMTkxXSwgYXNzdW1wdGlvbnMgPSBhc3N1bXB0aW9ucywgbnVtYmVyX3NwZWNpZXMgPSAyLCBpbml0aWFsX2ZyZXF1ZW5jeSA9IFtbMC41LCAwLjVdLCBbMC45NSwgMC4wNV0sIFswLjA1LCAwLjk1XV0pCmluaXRfc3RhdGUgPSBtYWtlX2luaXRpYWxfc3RhdGUoYXNzdW1wdGlvbnMsIE4wKQoKIyBNYWtlIHBsYXRlCnBsYXRlID0gQ29tbXVuaXR5KGluaXRfc3RhdGUsIGR5bmFtaWNzLCBwYXJhbXMsIHNjYWxlID0gMTAqKjYsIHBhcmFsbGVsID0gVHJ1ZSkKCiMgU2ltdWxhdGlvbgpzaW11bGF0ZV9jb21tdW5pdHkocGxhdGUsIGFzc3VtcHRpb25zLCBwYXJhbXNfc2ltdWxhdGlvbiwgZmlsZV9uYW1lID0gImRhdGEvc2VsZl9hc3NlbWJseS1wYWlyLVcwIiwgd3JpdGVfY29tcG9zaXRpb24gPSBUcnVlKQpgYGAKCgpQYWlyd2lzZSBjb21wZXRpdGlvbiBpbiBzZWxmLWFzc2VtYmxlZCBjb21tdW5pdHkgVzEKCmBgYHtweXRob259CiMgQXNzdW1wdGlvbnMKYXNzdW1wdGlvbnMgPSBhX2RlZmF1bHQuY29weSgpICMgU3RhcnQgd2l0aCBkZWZhdWx0IHBhcmFtZXRlcnMKYXNzdW1wdGlvbnMudXBkYXRlKHsnbl93ZWxscyc6OTYsICdjMScgOjAuMDEsICdtdWMnOjAuMSwgJ20nOjB9KSAjIFN3aXRjaCBvZmYgbW9ydGFsaXR5CgojIFByZXBhcmUgZXhwZXJpbWVudApwYXJhbXMsIHNwZWNpZXNfcG9vbCA9IHByZXBhcmVfZXhwZXJpbWVudChhc3N1bXB0aW9ucykKCiMjIFNpbXVsYXRpb24gcGFyYW1ldGVycwpwYXJhbXNfc2ltdWxhdGlvbiA9IHsKICAgICJuX3Byb3BhZ2F0aW9uIjogMTIsICMgTGVuZ3RoIG9mIHByb3BhZ2F0aW9uLCBvciBob3VycyB3aXRoaW4gYSBncm93dGggY3ljbGUKICAgICJuX3RyYW5zZmVyIjogMTAsICMgTnVtYmVyIG9mIHRyYW5zZmVyLCBvciBudW1iZXIgb2YgcGFzc2FnZQogICAgImRpbHV0aW9uIjogMS8xMDAwLCAjIERpbHV0aW9uIGZhY3RvciBmb3IgdHJhbnNmZXIKfQoKIyBNYWtlIGluaXRpYWwgc3RhdGUKTjAgPSBtYWtlX3N5bnRoZXRpY19jb21tdW5pdHkoc3BlY2llc19saXN0ID0gWzE4LCAyMSwgMzgsIDUxLCA5NCwgMTQyLCAxNTIsIDE1NSwgMTU4LCAxNzEsIDE4MywgMTg4XSwgYXNzdW1wdGlvbnMgPSBhc3N1bXB0aW9ucywgbnVtYmVyX3NwZWNpZXMgPSAyLCBpbml0aWFsX2ZyZXF1ZW5jeSA9IFtbMC41LCAwLjVdLCBbMC45NSwgMC4wNV0sIFswLjA1LCAwLjk1XV0pCmluaXRfc3RhdGUgPSBtYWtlX2luaXRpYWxfc3RhdGUoYXNzdW1wdGlvbnMsIE4wKQoKIyBNYWtlIHBsYXRlCnBsYXRlID0gQ29tbXVuaXR5KGluaXRfc3RhdGUsIGR5bmFtaWNzLCBwYXJhbXMsIHNjYWxlID0gMTAqKjYsIHBhcmFsbGVsID0gVHJ1ZSkKCiMgU2ltdWxhdGlvbgpzaW11bGF0ZV9jb21tdW5pdHkocGxhdGUsIGFzc3VtcHRpb25zLCBwYXJhbXNfc2ltdWxhdGlvbiwgZmlsZV9uYW1lID0gImRhdGEvc2VsZl9hc3NlbWJseS1wYWlyLVcxIiwgd3JpdGVfY29tcG9zaXRpb24gPSBUcnVlKQpgYGAKClBhaXJ3aXNlIGNvbXBldGl0aW9uIGluIHNlbGYtYXNzZW1ibGVkIGNvbW11bml0eSBXMgoKYGBge3B5dGhvbn0KIyBBc3N1bXB0aW9ucwphc3N1bXB0aW9ucyA9IGFfZGVmYXVsdC5jb3B5KCkgIyBTdGFydCB3aXRoIGRlZmF1bHQgcGFyYW1ldGVycwphc3N1bXB0aW9ucy51cGRhdGUoeyduX3dlbGxzJzo5NiwgJ2MxJyA6MC4wMSwgJ211Yyc6MC4xLCAnbSc6MH0pICMgU3dpdGNoIG9mZiBtb3J0YWxpdHkKCiMgUHJlcGFyZSBleHBlcmltZW50CnBhcmFtcywgc3BlY2llc19wb29sID0gcHJlcGFyZV9leHBlcmltZW50KGFzc3VtcHRpb25zKQoKIyMgU2ltdWxhdGlvbiBwYXJhbWV0ZXJzCnBhcmFtc19zaW11bGF0aW9uID0gewogICAgIm5fcHJvcGFnYXRpb24iOiAxMiwgIyBMZW5ndGggb2YgcHJvcGFnYXRpb24sIG9yIGhvdXJzIHdpdGhpbiBhIGdyb3d0aCBjeWNsZQogICAgIm5fdHJhbnNmZXIiOiAxMCwgIyBOdW1iZXIgb2YgdHJhbnNmZXIsIG9yIG51bWJlciBvZiBwYXNzYWdlCiAgICAiZGlsdXRpb24iOiAxLzEwMDAsICMgRGlsdXRpb24gZmFjdG9yIGZvciB0cmFuc2Zlcgp9CgojIE1ha2UgaW5pdGlhbCBzdGF0ZQpOMCA9IG1ha2Vfc3ludGhldGljX2NvbW11bml0eShzcGVjaWVzX2xpc3QgPSBbMTMsIDE2LCAxOCwgMjEsIDMzLCA2NiwgODUsIDExMCwgMTE1LCAxMTgsIDE1NSwgMTcxLCAxNzcsIDE5MV0sIGFzc3VtcHRpb25zID0gYXNzdW1wdGlvbnMsIG51bWJlcl9zcGVjaWVzID0gMiwgaW5pdGlhbF9mcmVxdWVuY3kgPSBbWzAuNSwgMC41XSwgWzAuOTUsIDAuMDVdLCBbMC4wNSwgMC45NV1dKQppbml0X3N0YXRlID0gbWFrZV9pbml0aWFsX3N0YXRlKGFzc3VtcHRpb25zLCBOMCkKCiMgTWFrZSBwbGF0ZQpwbGF0ZSA9IENvbW11bml0eShpbml0X3N0YXRlLCBkeW5hbWljcywgcGFyYW1zLCBzY2FsZSA9IDEwKio2LCBwYXJhbGxlbCA9IFRydWUpCgojIFNpbXVsYXRpb24Kc2ltdWxhdGVfY29tbXVuaXR5KHBsYXRlLCBhc3N1bXB0aW9ucywgcGFyYW1zX3NpbXVsYXRpb24sIGZpbGVfbmFtZSA9ICJkYXRhL3NlbGZfYXNzZW1ibHktcGFpci1XMiIsIHdyaXRlX2NvbXBvc2l0aW9uID0gVHJ1ZSkKYGBgCgoKClBhaXJ3aXNlIGNvbXBldGl0aW9uIGluIHNlbGYtYXNzZW1ibGVkIGNvbW11bml0eSBXMTQKCmBgYHtweXRob259CiMgQXNzdW1wdGlvbnMKYXNzdW1wdGlvbnMgPSBhX2RlZmF1bHQuY29weSgpICMgU3RhcnQgd2l0aCBkZWZhdWx0IHBhcmFtZXRlcnMKYXNzdW1wdGlvbnMudXBkYXRlKHsnbl93ZWxscyc6OTYsICdjMScgOjAuMDEsICdtdWMnOjAuMSwgJ20nOjB9KSAjIFN3aXRjaCBvZmYgbW9ydGFsaXR5CgojIFByZXBhcmUgZXhwZXJpbWVudApwYXJhbXMsIHNwZWNpZXNfcG9vbCA9IHByZXBhcmVfZXhwZXJpbWVudChhc3N1bXB0aW9ucykKCiMjIFNpbXVsYXRpb24gcGFyYW1ldGVycwpwYXJhbXNfc2ltdWxhdGlvbiA9IHsKICAgICJuX3Byb3BhZ2F0aW9uIjogMTIsICMgTGVuZ3RoIG9mIHByb3BhZ2F0aW9uLCBvciBob3VycyB3aXRoaW4gYSBncm93dGggY3ljbGUKICAgICJuX3RyYW5zZmVyIjogMTAsICMgTnVtYmVyIG9mIHRyYW5zZmVyLCBvciBudW1iZXIgb2YgcGFzc2FnZQogICAgImRpbHV0aW9uIjogMS8xMDAwLCAjIERpbHV0aW9uIGZhY3RvciBmb3IgdHJhbnNmZXIKfQoKIyBNYWtlIGluaXRpYWwgc3RhdGUKTjAgPSBtYWtlX3N5bnRoZXRpY19jb21tdW5pdHkoc3BlY2llc19saXN0ID0gWzEzLCAxNiwgMTgsIDIxLCA1MSwgNTIsIDc0LCA5NCwgMTE1LCAxMzgsIDE0MiwgMTUyLCAxNTUsIDE1OCwgMTcxLCAxNzcsIDE4MCwgMTgzLCAyMDBdLCBhc3N1bXB0aW9ucyA9IGFzc3VtcHRpb25zLCBudW1iZXJfc3BlY2llcyA9IDIsIGluaXRpYWxfZnJlcXVlbmN5ID0gW1swLjUsIDAuNV0sIFswLjk1LCAwLjA1XSwgWzAuMDUsIDAuOTVdXSkKaW5pdF9zdGF0ZSA9IG1ha2VfaW5pdGlhbF9zdGF0ZShhc3N1bXB0aW9ucywgTjApCgojIE1ha2UgcGxhdGUKcGxhdGUgPSBDb21tdW5pdHkoaW5pdF9zdGF0ZSwgZHluYW1pY3MsIHBhcmFtcywgc2NhbGUgPSAxMCoqNiwgcGFyYWxsZWwgPSBUcnVlKQoKIyBTaW11bGF0aW9uCnNpbXVsYXRlX2NvbW11bml0eShwbGF0ZSwgYXNzdW1wdGlvbnMsIHBhcmFtc19zaW11bGF0aW9uLCBmaWxlX25hbWUgPSAiZGF0YS9zZWxmX2Fzc2VtYmx5LXBhaXItVzE0Iiwgd3JpdGVfY29tcG9zaXRpb24gPSBUcnVlKQpgYGAKCgpSdW4gVzE0IGZvciBsb25nZXIKCmBgYHtweXRob259CiMgQXNzdW1wdGlvbnMKYXNzdW1wdGlvbnMgPSBhX2RlZmF1bHQuY29weSgpICMgU3RhcnQgd2l0aCBkZWZhdWx0IHBhcmFtZXRlcnMKYXNzdW1wdGlvbnMudXBkYXRlKHsnbl93ZWxscyc6OTYsICdjMScgOjAuMDEsICdtdWMnOjAuMSwgJ20nOjB9KSAjIFN3aXRjaCBvZmYgbW9ydGFsaXR5CgojIFByZXBhcmUgZXhwZXJpbWVudApwYXJhbXMsIHNwZWNpZXNfcG9vbCA9IHByZXBhcmVfZXhwZXJpbWVudChhc3N1bXB0aW9ucykKCiMjIFNpbXVsYXRpb24gcGFyYW1ldGVycwpwYXJhbXNfc2ltdWxhdGlvbiA9IHsKICAgICJuX3Byb3BhZ2F0aW9uIjogMTIsICMgTGVuZ3RoIG9mIHByb3BhZ2F0aW9uLCBvciBob3VycyB3aXRoaW4gYSBncm93dGggY3ljbGUKICAgICJuX3RyYW5zZmVyIjogMzAsICMgTnVtYmVyIG9mIHRyYW5zZmVyLCBvciBudW1iZXIgb2YgcGFzc2FnZQogICAgImRpbHV0aW9uIjogMS8xMDAwLCAjIERpbHV0aW9uIGZhY3RvciBmb3IgdHJhbnNmZXIKfQoKIyBNYWtlIGluaXRpYWwgc3RhdGUKTjAgPSBtYWtlX3N5bnRoZXRpY19jb21tdW5pdHkoc3BlY2llc19saXN0ID0gWzEzLCAxNiwgMTgsIDIxLCA1MSwgNTIsIDc0LCA5NCwgMTE1LCAxMzgsIDE0MiwgMTUyLCAxNTUsIDE1OCwgMTcxLCAxNzcsIDE4MCwgMTgzLCAyMDBdLCBhc3N1bXB0aW9ucyA9IGFzc3VtcHRpb25zLCBudW1iZXJfc3BlY2llcyA9IDIsIGluaXRpYWxfZnJlcXVlbmN5ID0gW1swLjUsIDAuNV0sIFswLjk1LCAwLjA1XSwgWzAuMDUsIDAuOTVdXSkKaW5pdF9zdGF0ZSA9IG1ha2VfaW5pdGlhbF9zdGF0ZShhc3N1bXB0aW9ucywgTjApCgojIE1ha2UgcGxhdGUKcGxhdGUgPSBDb21tdW5pdHkoaW5pdF9zdGF0ZSwgZHluYW1pY3MsIHBhcmFtcywgc2NhbGUgPSAxMCoqNiwgcGFyYWxsZWwgPSBUcnVlKQoKIyBTaW11bGF0aW9uCnNpbXVsYXRlX2NvbW11bml0eShwbGF0ZSwgYXNzdW1wdGlvbnMsIHBhcmFtc19zaW11bGF0aW9uLCBmaWxlX25hbWUgPSAiZGF0YS9zZWxmX2Fzc2VtYmx5LXBhaXItVzE0YSIsIHdyaXRlX2NvbXBvc2l0aW9uID0gVHJ1ZSkKYGBgCgojIyBQbG90IHJlc3VsdAoKYGBge3IgbWVzc2FnZSA9IEZ9CnNvdXJjZSgic2NyaXB0LzA0QS1zZWxmX2Fzc2VtYmx5LTAzLXJlYWRfcGFpcl9kYXRhLlIiKQpgYGAKCmBgYHtyfQppZih3cml0ZV9hbGxfY3N2KSBmd3JpdGUoZGZfcGFpcl9pbnRlcmFjdGlvbiwgcm9vdCRmaW5kX2ZpbGUoIm91dHB1dC9yZXBvcnQvZGF0YS90ZW1wL2RmX3BhaXJfaW50ZXJhY3Rpb24udHh0IikpCmBgYAoKCkxpc3Qgb2YgZ3Jvd2VyIGlkZW50aWZpZWQgYnkgbW9ub2N1bHR1cmUKCmBgYHtyfQpkZl9tb25vICU+JQogIGZpbHRlcihUeXBlID09ICJjb25zdW1lciIsIFRyYW5zZmVyID09IDEwKSAlPiUKICBwdWxsKElEKSAlPiUgYXMuY2hhcmFjdGVyKCkgJT4lIHBhc3RlMChjb2xsYXBzZSA9ICIsICIpCmBgYAoKClBhaXJ3aXNlIGNvbXBldGl0aW9uIGluIHNlbGYtYXNzZW1ibGVkIGNvbW11bml0aWVzCgpgYGB7cn0KcF9wYWlyCmBgYAoKCmBgYHtyfQpwZGYocm9vdCRmaW5kX2ZpbGUoIm91dHB1dC9yZXBvcnQvZmlndXJlLzA0QS1zZWxmX2Fzc2VtYmx5LVcxNF9wYWlyd2lzZV9jb21wZXRpdGlvbi5wZGYiKSk7IHBfcGFpcltbM11dOyBpbnZpc2libGUoZGV2Lm9mZigpKQoKcGRmKHJvb3QkZmluZF9maWxlKCJvdXRwdXQvcmVwb3J0L2ZpZ3VyZS8wNEEtc2VsZl9hc3NlbWJseS1XMTRhX3BhaXJ3aXNlX2NvbXBldGl0aW9uLnBkZiIpKTsgcF9wYWlyW1s0XV07IGludmlzaWJsZShkZXYub2ZmKCkpCmBgYAoKCgojIyBOdW1iZXIgb2YgaW50ZXJhY3Rpb24gdHlwZXMKCmBgYHtyIGZpZy53aWR0aCA9IDMsIGZpZy5oZWlnaHQgPSAyfQpwX2ludGVyYWN0aW9uX2ZyZXF1ZW5jeQoKcGRmKHJvb3QkZmluZF9maWxlKCJvdXRwdXQvcmVwb3J0L2ZpZ3VyZS8wNEEtc2VsZl9hc3NlbWJseS1wYWlyd2lzZV9pbnRlcmFjdGlvbnMucGRmIiksIHdpZHRoID0gOCwgaGVpZ2h0ID0gNSk7IHBfaW50ZXJhY3Rpb25fZnJlcXVlbmN5OyBpbnZpc2libGUoZGV2Lm9mZigpKQoKYGBgCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK